#include <stdio.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_random.h"
#include "esp_log.h"

#include "task_one.h"
#include "task_two.h"
// #include "task_pwm_out.h"
// #include "task_pwm_capture.h"
// #include "task_timer_out.h"
#include "uart1_cmd.h"

#include "xlx_define.h"
#include "xlx_core.h"

#include "xlx_utils.h"
#include "xlx_tmsapi.h"
#include "xlx_esp32xx_socket_demo.h"
#include "xlx_tms_service.h"
#include "xlx_tcpsocket.h"


#define MAIN_TASK_STACK_SIZE (2*1024)

static const char* TAG = "xlx_main";

TaskHandle_t main_task_handle;
TaskHandle_t recv_queeu_task_handle;
TaskHandle_t recv_queeu_task_handle2;

TutuQueueHandle h_tt;


void print_timer(void){
    time_t rawtime;
    struct tm * timeinfo;

    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
  
    TUTU_LOGI(TAG, "The current date/time is: %s", asctime (timeinfo) );      
}

/*
 * 线程回调
 * 专门收线程2发来的消息
*/
extern QueueHandle_t task2_send_queue;
static void receive_queue_cb(void *parameters){
    bool ret;

    TUTU_LOGI(TAG, "receice queue task is running...\r\n");

    while(1){       
        //
        task2_queue_msg_t msg;
        if(NULL == task2_send_queue){
             vTaskDelay(1000 / portTICK_PERIOD_MS); 
             continue;
        }
        ret = xQueueReceive(task2_send_queue, (void *)&msg, portMAX_DELAY);
        if(ret == false){
            TUTU_LOGE(TAG, "receice queue: NULL");
            continue;
        }

        TUTU_LOGI(TAG, "msg_id=%d, msg.len=%d, msg.buff= %s(ret=%d)",
            msg.msg_id,
            msg.msg_len,
            msg.msg_buff,
            ret
        );

        if(NULL != msg.msg_buff)
        {
            TUTU_LOGW(TAG, "Queue buff free!(addr@%p)", msg.msg_buff);
            free(msg.msg_buff);            
        }

    }
    vTaskDelete(NULL);
}

static void receive_queue_cb2(void *parameters){
    char ret;

    TUTU_LOGI(TAG, "receice queue2 task is running...\r\n");

    while(1){       
        //
        TutuQueueMsg msg;
        if(NULL == h_tt){
             vTaskDelay(1000 / portTICK_PERIOD_MS); 
             continue;
        }
        ret= g_tutuqueue.irecv(h_tt, (void *)&msg, portMAX_DELAY);
        if(ret == pdFALSE){
            TUTU_LOGE(TAG, "receice queue: NULL");
            continue;
        }

        TUTU_LOGI(TAG, "msg_id=%d, msg.len=%d, msg.buff= %s(ret=%d)",
            msg.msg_id,
            msg.data_len,
            msg.data,
            ret
        );

        if(NULL != msg.data)
        {
            TUTU_LOGW(TAG, "Queue buff free!(addr@%p)", msg.data);
            free(msg.data);            
        }

    }
    vTaskDelete(NULL);
}

/*
 * 线程回调
*/
static void main_task_cb(void *parameters){
    int tcp_tick = 0;

    TUTU_LOGI(TAG, "task_id=%d\r\n", *((int *)parameters));
    TUTU_LOGI(TAG, "main task is running...\r\n");
    while(1){       
        TutuQueueMsg msg;
        if(NULL == h_tt){
             vTaskDelay(1000 / portTICK_PERIOD_MS); 
             continue;
        }
        // fflush(stdout);  // 使用ESP_LOGI 不需要执行fflush
        vTaskDelay(5000 / portTICK_PERIOD_MS);         
        print_timer();

        // 发生一个随机大小到数据包
        unsigned int buff_size = esp_random();
        char * queue_buff;
        buff_size %= 32;
        buff_size += 1;

        TUTU_LOGI(TAG, "buff_size=%d", buff_size);
        queue_buff = malloc(buff_size);
    
        msg.msg_id = 10000+(buff_size%10);
        msg.data_len = buff_size;
        msg.data = queue_buff;

        memset(msg.data, 0x30+(buff_size%10), buff_size);
        msg.data[buff_size-1]= 0x00;

        if(queue_buff == NULL){
            TUTU_LOGE(TAG, "malloc2 ERROR!");
            continue;
        }else {
            TUTU_LOGW(TAG, "Queue2 malloc OK(%d@%p), msg_id=%d!",buff_size, queue_buff, msg.msg_id);
        }
        TUTUG(queue).isend(h_tt, &msg);

        tcp_tick++;
        if(tcp_tick == 2){

            tutucore_enter();
        }
    }
    vTaskDelete(NULL);
}

const int main_task_id = 100;
void main_task_init(void){
    int ret = 0;
    TUTU_LOGI(TAG, "-> %s(%s %s) ", __FUNCTION__, __DATE__, __TIME__);

    ret = xTaskCreate(main_task_cb, "main task", MAIN_TASK_STACK_SIZE,
                    (void *)&main_task_id, 5, &main_task_handle);
    
    if (ret != pdTRUE) {
        TUTU_LOGE(TAG, "%s(ret=%d)\r\n", "main task create fail!", ret);        

    }
    else {
         TUTU_LOGI(TAG, "%s(ret=%d)\r\n", "main task  create OK", ret);
    }

    ret = xTaskCreate(receive_queue_cb, "recv queqe", MAIN_TASK_STACK_SIZE,
                    NULL, 6, &recv_queeu_task_handle);    
    if (ret != pdTRUE) {
        TUTU_LOGE(TAG, "%s(ret=%d)\r\n", "recv queqe create fail!", ret);        

    }
    else {
         TUTU_LOGI(TAG, "%s(ret=%d)\r\n", "recv queqe create OK", ret);
    }

    ret = xTaskCreate(receive_queue_cb2, "recv queqe2", MAIN_TASK_STACK_SIZE,
                    NULL, 6, &recv_queeu_task_handle2);    
    if (ret != pdTRUE) {
        TUTU_LOGE(TAG, "%s(ret=%d)\r\n", "recv queqe2 create fail!", ret);        

    }
    else {
         TUTU_LOGI(TAG, "%s(ret=%d)\r\n", "recv queqe2 create OK", ret);
    }    
    
}

void xlx_queue_tt(void){    
    if(h_tt != NULL) {
        TUTU_LOGI(TAG, "=====================  QUEUE h_tt create OK =======================");
    }
    else {
        TUTU_LOGI(TAG, "=====================  QUEUE h_tt create Fail =======================");
    }    
}

#if 0
static TutuThreadHandle *g_xlx_task_thread = NULL;
void xlx_task_cb(void *params){
    unsigned int tcp_tick = 0;    
    while(1){
        vTaskDelay(3000 / portTICK_PERIOD_MS);
        TUTU_LOGI(TAG, "=.=");

        tcp_tick++;
        if(tcp_tick == 3){

            tutucore_enter();
        }
    }
    vTaskDelete(NULL);
}

void create_xlx_task(void){ 
    g_xlx_task_thread = g_tututhread.new_thread(2048,NULL, 11, xlx_task_cb);
}
#endif


void set_system_timer(void){

    char buf[64];
    struct tm tm = { 0 };
    tm.tm_year = 2024 - 1900;
    tm.tm_mon = 8-1;
    tm.tm_mday = 27;
    tm.tm_hour = 14;
    tm.tm_min = 59;
    tm.tm_sec = 21;
    time_t t = mktime(&tm);
    const char* time_str = asctime(&tm);
    strlcpy(buf, time_str, sizeof(buf));
    TUTU_LOGI(TAG, "Setting time: %s", time_str);
    struct timeval now = { .tv_sec = t };
    settimeofday(&now, NULL);  
}



void app_main(void)
{
    // esp_log_level_set(TAG, ESP_LOG_VERBOSE);
    TUTU_LOGI(TAG, "app main (portTICK_PERIOD_MS=%lu)\r\n", portTICK_PERIOD_MS);
    TUTU_LOGI(TAG, "=====================  xlx Smart ventilation fan =======================");
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());
    
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());
    main_task_init();
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());
    // task_one_init();
    task_two_init();
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());
    // 初始化core
    xlx_core_init();
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());

    xlx_esp32_socket_init();
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());
    // task_pwm_out_init();
    // task_pwm_capture_init();
    // task_timer_out_init();
    
    uart1_task_init();
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());

    g_tutuqueue.icreate(&h_tt, 10);     // 创建一个队列
    xlx_queue_tt();
    // create_xlx_task();
    TUTU_LOGI(TAG, "VER: %s", get_current_outside_sw_version());

    {
        char imei[16] = {0};
        xlx_imei_check("86861245801361", imei);
        TUTU_LOGI(TAG, "IMEI: %s", imei);

    }

    set_system_timer();    
    
    TUTU_LOGI(TAG, "Free heap: %ld\n", esp_get_free_heap_size());
    TUTU_LOGI(TAG, "  ------------------  xlx app end   -------------------");
}

